﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GFE.SharePoint.Interfaces;
using GFE.SharePoint.Attributes;
using GFE.SharePoint.Lazy;

namespace GFE.SharePoint.ModelFactory
{
    public class GFEModelFactory<Z>
    {
        public static Z CreateExtended<T>()
        {
            return default(Z);
        }
        public static Z CreateEmpty()
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            return ExportModelFactory.CreateEmpty((Z)modelExport.Value);
        }

        public static Z CreateFromDataRow(System.Data.DataRow dataRow)
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            return ExportModelFactory.CreateFromDataRow(dataRow, (Z)modelExport.Value);
        }

        public static Z CreateFromListItem(Microsoft.SharePoint.SPListItem listItem)
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            return ExportModelFactory.CreateFromListItem(listItem, (Z)modelExport.Value);
        }

        public static string CreateViewFields()
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            return ExportModelFactory.CreateViewFields();
        }

        public static void CreateSPListItem(ref Microsoft.SharePoint.SPListItem listItem)
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            ExportModelFactory.CreateSPListItem((Z)modelExport.Value, ref listItem);
        }

        public static Z CreateFromXelement(System.Xml.Linq.XElement element)
        {
            var modelExport = GFECompositionContainer.GetExportModel<Z>();
            if (modelExport == null) throw new Exception("No export defined for model : " + typeof(Z).ToString());

            var GFEModelFactoryAttributeObject = modelExport.Value.GetType().GetMEFAttribute<GFEModelFactoryAttribute>();
            if (GFEModelFactoryAttributeObject == null) throw new Exception("No GFEModelFactory attribute defined for model : " + typeof(Z).ToString());

            var ExportModelFactory = (IGFEModelFactory<Z>)GFECompositionContainer.GetExportModelFactory(GFEModelFactoryAttributeObject.ModelFactoryType.AssemblyQualifiedName).Value;
            if (ExportModelFactory == null) throw new Exception("No GFEModelFactory class defined for model : " + typeof(Z).ToString());

            return ExportModelFactory.CreateFromXelement(element, (Z)modelExport.Value);
        }
    }
}
